package cn.testfan.apitest.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;

import com.alibaba.fastjson.JSON;

public class HttpClientUtil {
	static PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
	static BasicCookieStore cookieStore = new BasicCookieStore();
	static CloseableHttpClient httpclient = null;

	static {
		cm.setMaxTotal(100);

		httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).setConnectionManager(cm).build();
	}

	public static CloseableHttpClient getHttpclient() {
		return httpclient;
	}

	public static BasicCookieStore getCookieStore() {
		return cookieStore;
	}

	public static String wrapUrl(String url, Map<String, String> params) {
		if (params == null)
			return url;
		StringBuilder urlBuilder = new StringBuilder(url);
		if (url.indexOf("?") < 0) {
			urlBuilder.append('?');
		}

		for (Map.Entry<String, String> entry : params.entrySet()) {
			urlBuilder.append('&').append(entry.getKey()).append('=').append(entry.getValue());
		}

		return urlBuilder.toString();
	}

	public static AbstractHttpEntity getRequestEntity(Map<String, String> parameters, String contentType) {
		List<BasicNameValuePair> params = new ArrayList<>();
		// 添加参数
		for (Map.Entry<String, String> me : parameters.entrySet()) {
			params.add(new BasicNameValuePair(me.getKey(), me.getValue()));
		}
		AbstractHttpEntity entity = null;
		if ("application/x-www-form-urlencoded".equals(contentType)) {
			entity = new UrlEncodedFormEntity(params, Charset.forName("UTF-8"));
		} else if ("application/json".equals(contentType)) {
			String json = JSON.toJSONString(parameters);
			entity = new StringEntity(json, Charset.forName("UTF-8"));
			entity.setContentType("application/json");
		} else if ("application/xml".equals(contentType)) {
			// TODO
			String xml = "";
			entity = new StringEntity(xml, Charset.forName("UTF-8"));
			entity.setContentType(contentType);
			// TODO
			throw new RuntimeException("TODO");
		} else if ("text/plain".equals(contentType)) {
			// TODO
			String text = "";
			entity = new StringEntity(text, Charset.forName("UTF-8"));
			entity.setContentType(contentType);
			// TODO
			throw new RuntimeException("TODO");
		} else if ("binary/octet-stream".equals(contentType)) {
			// TODO
			String text = "";
			entity = new StringEntity(text, Charset.forName("UTF-8"));
			entity.setContentType(contentType);
			// TODO
			String fileName = "";
			File file = new File(fileName);

			InputStreamEntity reqEntity = null;
			try {
				reqEntity = new InputStreamEntity(new FileInputStream(file), -1, ContentType.APPLICATION_OCTET_STREAM);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			reqEntity.setChunked(true);
			throw new RuntimeException("TODO");
		}
		return entity;
	}

	public static CloseableHttpResponse get(String url, Map<String, String> params, Header... header) {
		return get(url, params, null, header);
	}

	public static CloseableHttpResponse get(String url, Map<String, String> params, HttpContext context,
			Header... header) {
		HttpGet httpGet = new HttpGet(wrapUrl(url, params));
		for (Header h : header) {
			httpGet.addHeader(h);
		}
		CloseableHttpResponse response = null;
		try {
			response = httpclient.execute(httpGet, context);
			return response;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}

	public static CloseableHttpResponse post(String url, Map<String, String> dataMap, Header... header) {
		return post(url, dataMap, null, header);
	}

	public static CloseableHttpResponse post(String url, Map<String, String> dataMap, HttpContext context,
			Header... header) {
		HttpPost httpPost = new HttpPost(url);
		for (Header h : header) {
			httpPost.addHeader(h);
		}
		CloseableHttpResponse response = null;
		try {
			List<BasicNameValuePair> params = new ArrayList<>();
			for (String key : dataMap.keySet()) {
				String val = dataMap.get(key);
				params.add(new BasicNameValuePair(key, val));
			}
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, Charset.forName("UTF-8"));
			httpPost.setEntity(entity);
			response = httpclient.execute(httpPost, context);
			return response;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}

	public static CloseableHttpResponse put(String url, Map<String, String> dataMap, Header... header) {
		return put(url, dataMap, header);
	}

	public static CloseableHttpResponse put(String url, Map<String, String> dataMap, HttpContext context,
			Header... header) {
		HttpPut httpPut = new HttpPut(url);
		for (Header h : header) {
			httpPut.addHeader(h);
		}
		CloseableHttpResponse response = null;
		try {
			List<BasicNameValuePair> params = new ArrayList<>();
			for (String key : dataMap.keySet()) {
				String val = dataMap.get(key);
				params.add(new BasicNameValuePair(key, val));
			}
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, Charset.forName("UTF-8"));
			httpPut.setEntity(entity);
			response = httpclient.execute(httpPut);
			return response;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}

	public static CloseableHttpResponse delete(String url, Map<String, String> params, Header... header) {
		return delete(url, params, header);
	}

	public static CloseableHttpResponse delete(String url, Map<String, String> params, HttpContext context,
			Header... header) {
		HttpDelete httpDelete = new HttpDelete(wrapUrl(url, params));
		for (Header h : header) {
			httpDelete.addHeader(h);
		}
		CloseableHttpResponse response = null;
		try {
			response = httpclient.execute(httpDelete);
			return response;
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e.getCause());
		}
	}
}
